
package com.netease.xone.widget.msgbubble;

import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;

public class MessageBubble {

    // 缩放比例
    private static final float RATE_ICON = .6f;
    private static final float RATE_TITLE_TEXT = .4f;
    private static final float RATE_COUNT_TEXT = .5f;

    // 相关信息
    private String mTitle;
    private int mMessageCount;
    // 刚体属性
    private Body mBody;
    // 真实宽高
    private int mRadius;
    private int mWidth;
    private int mHeight;
    // 绘制属性
    private int mCountTextSize;// 数量字体字体大小
    private int mTitleTextSize;// 标题字体大小
    private Drawable mIconDrawable;
    private int mDrawWidth;
    private int mDrawHeight;
    private Paint mCountTextPaint;
    private Paint mTitleTextPaint;
    private Drawable mShadowDrawable;
    // 呼吸效果相关
    private int mMaxBreathLevel = 5;// 呼吸效果形变，参数越大效果越明显
    private float mBreathRate = .1f;// 呼吸频率，越高越快[0-1]
    private int mBreathLevel = mMaxBreathLevel / 2;// 当前Level
    private boolean mIsXStretch;// 标识当前是X轴还是Y轴在拉伸
    private float mNeedBreath;// 用于控制呼吸平率
    // 抖动相关
    private final int mMaxJiggleFrame = 20;// 最大抖动帧
    private int mMaxJiggleLevel = 3;// 抖动形变参数
    private int mJiggleTimes = 4;// 抖动次数
    private boolean mIsJiggling;// 是否抖动中
    private int mJiggleFrame;// 抖动帧
    // Touch相关
    private final int mMaxTouchFrame = 20;// 点击效果绘制最大帧数
    private Paint mTouchPaint;
    private boolean mIsOnTouch;
    private int mTouchFrame;
    private Paint mBubblePaint;

    // public MessageBubble(Drawable drawable, Body body, String title) {
    // mTitle = title;
    // mDrawable = drawable;
    // // mBitmap = bitmap;
    // mBody = body;
    // mBody.m_userData = this;
    // mWidth = mDrawable.getIntrinsicWidth();
    // mHeight = mDrawable.getIntrinsicHeight();
    // mDrawWidth = mWidth;
    // mDrawHeight = mHeight;
    // // 初始化文字绘制属性
    // mCountTextPaint = new Paint();
    // mCountTextPaint.setTextSize(mTextSize);
    // mCountTextPaint.setAntiAlias(true);
    // mCountTextPaint.setColor(Color.WHITE);
    // mCountTextPaint.setAlpha(200);
    // // 初始化Touch绘制
    // mTouchPaint = new Paint();
    // mTouchPaint.setColor(Color.WHITE);
    // mTouchPaint.setAntiAlias(true);
    // }

    private void resetDrawSize() {
        // 计算参数
        mRadius = (int)(mBody.getFixtureList().getShape().m_radius * MyBox2d.SCALE_RATE);
        mWidth = (int)(mBody.getFixtureList().getShape().m_radius * MyBox2d.SCALE_RATE * 2);
        mHeight = (int)(mBody.getFixtureList().getShape().m_radius * MyBox2d.SCALE_RATE * 2);
        // 计算字体大小
        mTitleTextSize = (int)(mRadius * RATE_TITLE_TEXT);
        mCountTextSize = (int)(mRadius * RATE_COUNT_TEXT);
        mDrawWidth = mWidth;
        mDrawHeight = mHeight;
    }

    public MessageBubble(Drawable icon, Drawable shadow, Body body, String title, boolean b) {
        //
        mTitle = title;
        // mBitmap = bitmap;
        mBody = body;
        mBody.m_userData = this;
        //
        resetDrawSize();
        // 初始化文字绘制属性
        mCountTextPaint = new Paint();
        mCountTextPaint.setTextSize(mCountTextSize);
        mCountTextPaint.setAntiAlias(true);
        mCountTextPaint.setColor(Color.WHITE);
        mCountTextPaint.setAlpha(200);
        mTitleTextPaint = new Paint();
        mTitleTextPaint.setTextSize(mTitleTextSize);
        mTitleTextPaint.setAntiAlias(true);
        mTitleTextPaint.setColor(Color.WHITE);
        mTitleTextPaint.setAlpha(200);
        // 初始化Touch绘制
        mTouchPaint = new Paint();
        mTouchPaint.setColor(Color.WHITE);
        mTouchPaint.setAntiAlias(true);
        // 初始化直接bubble绘制
        mBubblePaint = new Paint();
        mBubblePaint.setAntiAlias(true);
        // mBubblePaint.setColor(0xccc2cccc);
        // shadow
        mIconDrawable = icon;
        mShadowDrawable = shadow;
    }

    public void draw(Canvas canvas) {
        if (mMessageCount > 0) {
            mBubblePaint.setColor(0xff11a2e5);
            mCountTextPaint.setColor(Color.WHITE);
            mTitleTextPaint.setColor(Color.WHITE);
        } else {
            mBubblePaint.setColor(0xccc2cccc);
            mCountTextPaint.setColor(Color.BLACK);
            mTitleTextPaint.setColor(Color.BLACK);
        }
        if (mIsJiggling) {
            jiggle();
        } else {
            breath();
        }
        final int x = (int)(mBody.getPosition().x * MyBox2d.SCALE_RATE);
        final int y = (int)(mBody.getPosition().y * MyBox2d.SCALE_RATE);

        // 根据count计算缩放
        final int drawWidth = mDrawWidth;
        final int drawHeight = mDrawHeight;

        final String countString = String.valueOf(mMessageCount);
        final String titleString = mTitle;
        float countWidths[] = new float[countString.length()];
        float titleWidths[] = new float[titleString.length()];
        mTitleTextPaint.getTextWidths(titleString, titleWidths);
        mCountTextPaint.getTextWidths(countString, countWidths);
        float countTextWidth = 0;
        for (float width : countWidths) {
            countTextWidth += width;// 计算文字宽度，用于将文字绘于中心
        }
        float titleTextWidth = 0;
        for (float width : titleWidths) {
            titleTextWidth += width;// 计算文字宽度，用于将文字绘于中心
        }

        // 绘制阴影
        if(mShadowDrawable != null){
            canvas.save();
            canvas.translate(-drawWidth / 2, -drawHeight / 4);
            mShadowDrawable.setBounds(x, y, x + drawWidth, y + drawHeight);
            mShadowDrawable.draw(canvas);
            canvas.restore();
        }
        // 绘制泡泡, 直接绘制形状
        canvas.save();
        canvas.translate(-drawWidth / 2, -drawHeight / 2);
        canvas.drawOval(new RectF(x, y, x + drawWidth, y + drawHeight), mBubblePaint);
        canvas.restore();
        // 绘制资源
        canvas.save();
        int iconDrawWidth = (int)(drawWidth * RATE_ICON);
        int iconDrawHeight = (int)(drawHeight * RATE_ICON);
        canvas.translate(-iconDrawWidth / 2, -iconDrawHeight / 2);
        mIconDrawable.setBounds(x, y, x + iconDrawWidth, y + iconDrawHeight);
        mIconDrawable.draw(canvas);
        canvas.restore();
        // 绘制文字
        canvas.save();
        canvas.translate(-countTextWidth / 2, mDrawHeight / 3);
        mCountTextPaint.setTextScaleX((float)drawWidth / mWidth);
        canvas.drawText(countString, x, y, mCountTextPaint);
        canvas.restore();
        canvas.save();
        canvas.translate(-titleTextWidth / 2, 0);
        mTitleTextPaint.setTextScaleX((float)drawWidth / mWidth);
        canvas.drawText(titleString, x, y, mTitleTextPaint);
        canvas.restore();
        // 绘制Touch
        canvas.save();
        canvas.translate(-drawWidth / 2, -drawHeight / 2);
        if (mIsOnTouch) {
            if (mTouchFrame < mMaxTouchFrame) {
                mTouchPaint.setAlpha(mTouchPaint.getAlpha() / 2);
                canvas.drawOval(new RectF(x, y, x + drawWidth, y + drawHeight), mTouchPaint);
            } else {
                onTouchEnd();
            }
            mTouchFrame++;
        }
        canvas.restore();
    }

    /**
     * 呼吸效果
     */
    public void breath() {
        mNeedBreath += mBreathRate;
        if (mNeedBreath >= 1) {
            mNeedBreath = mNeedBreath - (int)mNeedBreath;

            if (mIsXStretch) {
                mDrawWidth += 1;
                mDrawHeight -= 1;
            } else {
                mDrawWidth -= 1;
                mDrawHeight += 1;
            }
            mBreathLevel++;
            if (mBreathLevel > mMaxBreathLevel) {
                mBreathLevel = 0;
                mIsXStretch = !mIsXStretch;
            }
        }
    }

    /**
     * 抖动
     */
    private void jiggle() {
        if (mJiggleFrame < mMaxJiggleFrame) {
            if (mIsXStretch) {
                mDrawWidth += mMaxJiggleLevel - mJiggleFrame / (mMaxJiggleFrame / mJiggleTimes);
                mDrawHeight -= mMaxJiggleLevel - mJiggleFrame / (mMaxJiggleFrame / mJiggleTimes);
            } else {
                mDrawWidth -= mMaxJiggleLevel - mJiggleFrame / (mMaxJiggleFrame / mJiggleTimes);
                mDrawHeight += mMaxJiggleLevel - mJiggleFrame / (mMaxJiggleFrame / mJiggleTimes);
            }
            mJiggleFrame++;
            if (mJiggleFrame % (mMaxJiggleFrame / mJiggleTimes) == mMaxJiggleFrame / mJiggleTimes
                    / 2) {
                mIsXStretch = !mIsXStretch;
            }
        } else {
            stopJiggle();
        }
    }

    public void startJiggle() {
        mBreathLevel = mMaxBreathLevel / 2;
        mDrawWidth = mWidth;
        mDrawHeight = mHeight;
        mJiggleFrame = 0;
        mIsJiggling = true;
    }

    public void stopJiggle() {
        mBreathLevel = mMaxBreathLevel / 2;
        mDrawWidth = mWidth;
        mDrawHeight = mHeight;
        mIsJiggling = false;
    }

    /**
     * 被点击
     *
     * @param touchX
     * @param touchY
     */
    public void onTouch(float touchX, float touchY) {
        final float x = mBody.getPosition().x;
        final float y = mBody.getPosition().y;
        mBody.setLinearVelocity(new Vec2((x - touchX) * 1.5f, (y - touchY) * 1.5f));
        onTouchStart();
    }

    /**
     * 点击开始
     */
    private void onTouchStart() {
        mTouchFrame = 0;
        mTouchPaint.setAlpha(255);
        mIsOnTouch = true;
        startJiggle();
    }

    /**
     * 点击结束
     */
    private void onTouchEnd() {
        mIsOnTouch = false;
        if (mClickListener != null)
            mClickListener.onBubbleClick(mTitle);
    }

    /**
     * 消息数量
     *
     * @param count
     */
    public void setMessageCount(int count) {
        mMessageCount = count;
        float rate = mMessageCount / 6f;
        int amplify = (int)(Math.min(rate, 1) * mRadius * 0.25 / MyBox2d.SCALE_RATE + Math.min(
                Math.max(rate - 1, 0), 2)
                * mRadius * 0.075 / MyBox2d.SCALE_RATE);
        float ori = mBody.getFixtureList().getShape().m_radius;
        mBody.getFixtureList().getShape().m_radius = ori + amplify;
        resetDrawSize();
    }

    private OnBubbleClickListener mClickListener;

    public void setOnBubbleClickListener(OnBubbleClickListener listener) {
        mClickListener = listener;
    }

    public interface OnBubbleClickListener {

        public void onBubbleClick(String title);
    }

}
